home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 426-450 / disk_439 / curses / src / curses.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  45KB  |  1,735 lines

  1. /*
  2.  *
  3.  * Module       : curses.c
  4.  *
  5.  * Description  : AMIGA CURSES package.
  6.  *
  7.  * Author       : Simon Raybould  (sie@fulcrum.bt.co.uk)
  8.  *
  9.  * Date  V1.00a : 16th February 1990
  10.  *       V1.10  : 30th July 1990
  11.  *       V1.20a :  4th October 1990
  12.  *       V1.20  :  7th November 1990
  13.  *       V1.21  :  2nd December 1990 minor fixes
  14.  *       V1.22  :  7th January 1991 bug fixes
  15.  *
  16.  */
  17.  
  18.  
  19. #include <intuition/intuition.h>
  20. #include <intuition/intuitionbase.h>
  21. #include <intuition/screens.h>
  22. #include <exec/types.h>
  23. #include <exec/memory.h>
  24. #include <devices/audio.h>
  25.  
  26. #include "acurses.h"
  27.  
  28.  
  29. /* Main background screen */
  30. static struct NewScreen NewScreen = {
  31.   0,                        /* LeftEdge */
  32.   0,                        /* TopEdge */
  33.   0,                        /* Width */
  34.   0,                        /* Height */
  35.   4,                        /* No. Bitplanes */
  36.   0, 1,                     /* DetailPen, BlockPen */
  37.   HIRES,                    /* ViewModes */
  38.   CUSTOMSCREEN,             /* Screen type */
  39.   (struct TextAttr *)NULL,  /* default font */
  40.   "Curses screen",          /* Screen Title */
  41.   (struct Gadget *)NULL,    /* Gadget list */
  42.   (struct BitMap *)NULL     /* custom bitmap */
  43. };
  44.  
  45. /* Main background window */
  46. static struct NewWindow NewWindow = {
  47.   0,                      /* Left edge */
  48.   0,                      /* Top edge */
  49.   0,                      /* Width */
  50.   0,                      /* Height */
  51.   -1, -1,                 /* Pens */
  52.   RAWKEY,                 /* IDCMP flags */
  53.   ACTIVATE | BORDERLESS,  /* Window flags */
  54.   NULL,                   /* First gadget */
  55.   NULL,                   /* Image data */
  56.   NULL,                   /* Title */
  57.   NULL,                   /* Pointer to screen structure */
  58.   NULL,                   /* Super BitMap ? */
  59.   0,0,0,0,                /* MIN/MAX sizing */
  60.   CUSTOMSCREEN            /* Type of screen */
  61. };
  62.  
  63. /*
  64.  *  Make author appear when right mouse button is pressed.
  65.  */
  66.  
  67. static struct Menu _CursesMenu = {
  68.   NULL, 0, 0, 0, 0, 0,
  69.   "  AMIGA CURSES by Simon J Raybould  (sie@fulcrum.bt.co.uk) V1.22  07.Jan.1991",
  70.   NULL, 0, 0, 0, 0
  71. };
  72.  
  73. /*
  74.  * Should initialise all of these to NULL to be certain that
  75.  * CleanExit() will function correctly. Most compilers will do this
  76.  * anyway, but better safe than GURUed.
  77.  */
  78.  
  79. struct IntuitionBase *IntuitionBase = NULL;
  80. struct GfxBase *GfxBase = NULL;
  81.  
  82. struct ConsoleDevice *ConsoleDevice = NULL;
  83. static struct IOStdReq ioreq;
  84. static struct Screen *CursesScreen = NULL;
  85. static struct Window *CursesWindow = NULL;
  86.  
  87. static struct RastPort *RPort;
  88. static struct ViewPort *VPort;
  89.  
  90. static unsigned char CursesFlags;  /* Global flags */
  91. static short CursorCol = 0,CursorLine = 0,LCursorLine = -1,LCursorCol = -1;
  92. static struct WindowState *HeadWindowList = (struct WindowState *)NULL;
  93. static struct RefreshElement *HeadRefreshList=(struct RefreshElement *)NULL;
  94. static struct IOAudio *AIOptr;
  95. static struct MsgPort *port;
  96. static ULONG device;
  97. static BYTE *sound_data;
  98. static UBYTE whichannel[] = { 1, 2, 4, 8 };
  99.  
  100. /*
  101.  *  void internal functions
  102.  */
  103.  
  104. static void CleanExit(), CleanUp(), DoEcho();
  105. static void ZapCursor(), DrawCursor();
  106.      
  107. /* Define a blank mouse pointer */
  108. static USHORT __chip MyMsPtr[] = { 0, 0, 0, 0 };
  109.      
  110. #define NCOLOURS  32
  111.      
  112. static UWORD ColourTable[] = {
  113.   0x000, 0xfff, 0xff0, 0xf80, 0x00f, 0xf0f, 0x0ff, 0xfff, 
  114.   0x620, 0xe50, 0x9f1, 0xeb0, 0x55f, 0x92f, 0x0f8, 0xccc, 
  115.   0x000, 0xd22, 0x000, 0xabc, 0x444, 0x555, 0x666, 0x777, 
  116.   0x888, 0x999, 0xaaa, 0xbbb, 0xccc, 0xddd, 0xeee, 0xfff
  117. };
  118.  
  119. WINDOW *stdscr = (WINDOW *)NULL, *curscr = (WINDOW *)NULL;
  120. int LINES=24, COLS=80;  /* Defaults */
  121.  
  122. /*
  123.  *  Need to be global so that flushinp() can reset them !
  124.  */
  125. static unsigned char GetchRPos = 0, GetchWPos = 0;
  126.  
  127. /*
  128.  *  Start of code.
  129.  */
  130.  
  131. initscr()
  132. {
  133.   ULONG IBaseLock;
  134.   char *Ptr, *getenv();
  135.   int Tmp;
  136.   
  137.   /*
  138.    *  It would be devestating if someone called initscr() twice
  139.    *  so make the second call fail.
  140.    */
  141.   if(CursesFlags & CFLAG_INITSCR)
  142.     return ERR;
  143.   
  144.   CursesFlags |= CFLAG_INITSCR;  /* Mark that we have called initscr() */
  145.   
  146.   if((IntuitionBase = (struct IntuitionBase *)
  147.       OpenLibrary("intuition.library", 0)) == NULL) {
  148.     fprintf(stderr, "Failed to open Intuition library");
  149.     CleanExit(10);
  150.   }
  151.   IBaseLock = LockIBase(0L);
  152.   NewScreen.Height = NewWindow.Height = IntuitionBase->ActiveScreen->Height;
  153.   NewScreen.Width = NewWindow.Width = IntuitionBase->ActiveScreen->Width;
  154.   UnlockIBase(IBaseLock);
  155.   /* Set interlace if height >= 400 */
  156.   if(NewScreen.Height>=400)
  157.     NewScreen.ViewModes |= LACE;
  158.   LINES = NewScreen.Height/8;
  159.   COLS = NewScreen.Width/8;
  160.   /* if LINES and/or COLS set as environment variables then use them */
  161.   if((Ptr = getenv("LINES"))) {
  162.     Tmp = atoi(Ptr);
  163.     if(Tmp>0 && Tmp<=LINES)
  164.       LINES = Tmp;
  165.   }
  166.   if((Ptr = getenv("COLS"))) {
  167.     Tmp = atoi(Ptr);
  168.     if(Tmp>0 && Tmp<=COLS)
  169.       COLS = Tmp;
  170.   }
  171.   /* Open graphics library */
  172.   if((GfxBase = (struct GfxBase *)
  173.       OpenLibrary("graphics.library", 0))==NULL) {
  174.     fprintf(stderr, "Failed to open Graphics library");
  175.     CleanExit(10);
  176.   }
  177.   /*
  178.    * must have the console.device opened to use RawKeyConvert()
  179.    */
  180.   
  181.   if(OpenDevice("console.device",-1L,(struct IORequest *)&ioreq,0L))
  182.     CleanExit(10);
  183.   ConsoleDevice=(struct ConsoleDevice *)ioreq.io_Device;
  184.   
  185.   if((CursesScreen=(struct Screen *)OpenScreen(&NewScreen)) == NULL) {
  186.     fprintf(stderr, "Failed to open Screen");
  187.     CleanExit(10);
  188.   }
  189.   RPort = &(CursesScreen->RastPort);
  190.   VPort = &(CursesScreen->ViewPort);
  191.   LoadRGB4(VPort, ColourTable, NCOLOURS);
  192.   SetDrMd(RPort, JAM2);
  193.   SetAPen(RPort, 1);
  194.   NewWindow.Screen = CursesScreen;  /* Must do this !! */
  195.   if((CursesWindow=(struct Window *)OpenWindow(&NewWindow)) == NULL) {
  196.     fprintf(stderr, "Failed to open Window\n");
  197.     CleanExit(10);
  198.   }
  199.   SetMenuStrip(CursesWindow, &_CursesMenu);
  200.   SetPointer(CursesWindow, MyMsPtr, 0, 0, 0, 0);  /*Remove mouse pointer*/
  201.   /* Create stdscr and curscr */
  202.   stdscr = newwin(LINES, COLS, 0, 0);
  203.   curscr = newwin(LINES, COLS, 0, 0);  /* used for redraws */
  204.   clearok(curscr, TRUE);  /* Clear curscr on every refresh */
  205.   
  206.   CursesFlags = CFLAG_ECHO | CFLAG_NLCR | CFLAG_CURSOR | CFLAG_INITSCR;
  207.   return OK;
  208. }
  209.  
  210. /*
  211.  *  Close the screen and libraries.
  212.  */
  213.  
  214. endwin()                  /* called from main prior to exit. */
  215. {
  216.   void ZapWindows();
  217.   
  218.   if(!(CursesFlags & CFLAG_INITSCR)) {  /* haven't called initscr() */
  219.     return ERR;
  220.   }
  221.   ZapWindows(HeadWindowList);
  222.   CleanUp();
  223.   CursesFlags &= ~CFLAG_INITSCR;  /* Mark that we have called endwin() */
  224.   return OK;
  225. }
  226.  
  227. /* Recursive routine to zap all windows and release data structures */
  228. static void ZapWindows(WinStat)
  229.      struct WindowState *WinStat;
  230. {
  231.   if(!WinStat)
  232.     return;
  233.   if(WinStat->Next)
  234.     ZapWindows(WinStat->Next);  /* Recurse */
  235.   delwin(&WinStat->Window);
  236. }
  237.  
  238. static void CleanExit(RetCode)
  239.      int RetCode;
  240. {
  241.   CleanUp();
  242.   exit(RetCode);
  243. }
  244.  
  245. static void CleanUp()
  246. {
  247.   if(CursesWindow)
  248.     CloseWindow(CursesWindow);
  249.   if(CursesScreen)
  250.     CloseScreen(CursesScreen);
  251.   if(GfxBase)
  252.     CloseLibrary((struct Library *)GfxBase);
  253.   if(IntuitionBase)
  254.     CloseLibrary((struct Library *)IntuitionBase);
  255. }
  256.  
  257. init_color(n, r, g, b)
  258.      short n;
  259.      unsigned char r, g, b;
  260. {
  261.   if(n<0 || n>15 || r>1000 || g>1000 || b>1000)
  262.     return ERR;
  263.   /* If 0 then leave, else subtract 1 */
  264.   if(r) r--;
  265.   if(g) g--;
  266.   if(g) g--;
  267.   
  268.   SetRGB4(VPort, n, r*16/1000, g*16/1000, b*16/1000);
  269.   return OK;
  270. }
  271.  
  272. start_color()
  273. {
  274.   return OK;  /* No initialisation required to get colours going */
  275. }
  276.  
  277. has_colors()
  278. {
  279.   return TRUE;  /* Yes baby we have colours on this bitch */
  280. }
  281.  
  282. /*
  283.  *  static because not implemented yet.
  284.  */
  285. static color_content(color, r, g, b)
  286.      short color, *r, *g, *b;
  287. {
  288.   return OK;
  289. }
  290.  
  291. waddstr(WinPtr, Str)
  292.      WINDOW *WinPtr;
  293.      char *Str;
  294. {
  295.   struct WindowState *WinStat, *PWinStat = NULL;
  296.   short TmpAttrs;
  297.   
  298.   if(!*Str)
  299.     return OK;
  300.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  301.     return ERR;
  302.   if(WinStat->ParentWin)
  303.     if(!(PWinStat = (struct WindowState *)WinStat->ParentWin->_WinStat))
  304.       return ERR;
  305.   
  306.   WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
  307.   WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
  308.   if(PWinStat) {
  309.     PWinStat->LnArry[WinPtr->_cury + WinPtr->_begy].Touched = TRUE;
  310.     PWinStat->LnArry[WinPtr->_cury + WinPtr->_begy].StartCol = min(PWinStat->LnArry[WinPtr->_cury + WinPtr->_begy].StartCol, WinPtr->_curx + WinPtr->_begx);
  311.   }
  312.   while(*Str) {
  313.     switch(*Str) {
  314.     case '\t':
  315.       do {
  316.     WinStat->LnArry[WinPtr->_cury].Line[WinPtr->_curx] = ' ';
  317.     WinStat->LnArry[WinPtr->_cury].ATTRS[WinPtr->_curx++] = WinPtr->_attrs;
  318.       } while(WinPtr->_curx % 8);
  319.       break;
  320.     case '\n':
  321.       WinStat->LnArry[WinPtr->_cury].EndCol = max(WinStat->LnArry[WinPtr->_cury].EndCol, WinPtr->_curx - 1);
  322.       TmpAttrs = WinPtr->_attrs;
  323.       wattrset(WinPtr, 0); /* better to call wattrset in case I change attrs */
  324.       wclrtoeol(WinPtr);
  325.       wattrset(WinPtr, TmpAttrs);
  326.       if(PWinStat)
  327.     PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol=max(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol,WinPtr->_curx+WinPtr->_begx-1);
  328.       WinPtr->_curx = 0;
  329.       WinPtr->_cury++;
  330.       if(WinPtr->_cury > WinStat->ScrollBot) {
  331.     if(WinPtr->_scroll)
  332.       scroll(WinPtr);
  333.     WinPtr->_cury = WinStat->ScrollBot;
  334.       }
  335.       if(*(Str + 1)) {  /* If there is more then touch this line too */
  336.     WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
  337.     WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
  338.     if(PWinStat) {
  339.       PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].Touched = TRUE;
  340.       PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol = min(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol, WinPtr->_curx+WinPtr->_begx);
  341.     }
  342.       }
  343.       break;
  344.     default:
  345.       WinStat->LnArry[WinPtr->_cury].Line[WinPtr->_curx] = *Str;
  346.       WinStat->LnArry[WinPtr->_cury].ATTRS[WinPtr->_curx] = WinPtr->_attrs;
  347.       WinPtr->_curx++;
  348.       break;
  349.     }
  350.     /* If hit right edge of window then increment _cury */
  351.     if(WinPtr->_curx > WinPtr-> _maxx) {
  352.       WinStat->LnArry[WinPtr->_cury].EndCol = max(WinStat->LnArry[WinPtr->_cury].EndCol, WinPtr->_curx - 1);
  353.       WinPtr->_curx = 0;
  354.       WinPtr->_cury++;
  355.       if(WinPtr->_cury > WinStat->ScrollBot) {
  356.     if(WinPtr->_scroll)
  357.       scroll(WinPtr);
  358.     WinPtr->_cury = WinStat->ScrollBot;
  359.       }
  360.       if(WinPtr->_cury > WinPtr->_maxy)
  361.     WinPtr->_cury = WinPtr->_maxy;
  362.       if(*(Str + 1)) {  /* If there is more then touch this line too */
  363.     WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
  364.     WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
  365.     if(PWinStat) {
  366.       PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].Touched = TRUE;
  367.       PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol = min(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol, WinPtr->_curx+WinPtr->_begx);
  368.     }
  369.       }
  370.     }
  371.     Str++;
  372.   }
  373.   WinStat->LnArry[WinPtr->_cury].EndCol = max(WinStat->LnArry[WinPtr->_cury].EndCol, WinPtr->_curx - 1);
  374.   if(PWinStat)
  375.     PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol = max(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol, WinPtr->_curx+WinPtr->_begx-1);
  376.   return OK;
  377. }
  378.  
  379. waddch(WinPtr, c)
  380.      WINDOW *WinPtr;
  381.      char c;
  382. {
  383.   char *str = " ";
  384.   
  385.   *str = c;
  386.   return waddstr(WinPtr, str);
  387. }
  388.  
  389. winsch(WinPtr, c)
  390.      WINDOW *WinPtr;
  391.      char c;
  392. {
  393.   int i;
  394.   struct WindowState *WinStat;
  395.   
  396.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  397.     return ERR;
  398.   
  399.   /* shuffle line along to the right */
  400.   for (i = WinPtr->_maxx; i > WinPtr->_curx; i--)
  401.     WinStat->LnArry[WinPtr->_cury].Line[i] = WinStat->LnArry[WinPtr->_cury].Line[i-1];
  402.   WinStat->LnArry[WinPtr->_cury].Line[i] = c;
  403.   WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
  404.   WinStat->LnArry[WinPtr->_cury].EndCol = WinPtr->_maxx;
  405.   WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
  406.   
  407.   return OK;
  408. }
  409.  
  410. wdelch(WinPtr)
  411.      WINDOW *WinPtr;
  412. {
  413.   int i;
  414.   struct WindowState *WinStat;
  415.   
  416.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  417.     return ERR;
  418.   
  419.   /* shuffle line along to the left */
  420.   for (i = WinPtr->_curx; i < WinPtr->_maxx; i++)
  421.     WinStat->LnArry[WinPtr->_cury].Line[i] = WinStat->LnArry[WinPtr->_cury].Line[i+1];
  422.   WinStat->LnArry[WinPtr->_cury].Line[i] = ' ';  /* Blank last char */
  423.   WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
  424.   WinStat->LnArry[WinPtr->_cury].EndCol = WinPtr->_maxx;
  425.   WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
  426.   
  427.   return OK;
  428. }
  429.  
  430. wclear(WinPtr)
  431.      WINDOW *WinPtr;
  432. {
  433.   int Line, Col;
  434.   struct WindowState *WinStat;
  435.   
  436.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  437.     return ERR;
  438.   
  439.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  440.     return ERR;
  441.   
  442.   for(Line=0; Line<WinStat->NLines; Line++) {
  443.     memset(WinStat->LnArry[Line].Line, ' ', WinPtr->_maxx + 1);
  444.     memset(WinStat->LnArry[Line].LRLine, ' ', WinPtr->_maxx + 1);
  445.     for(Col = 0; Col <= WinPtr->_maxx; Col++) {
  446.       WinStat->LnArry[Line].ATTRS[Col] = WinPtr->_attrs;
  447.       WinStat->LnArry[Line].LRATTRS[Col] = WinPtr->_attrs;
  448.     }
  449.     WinStat->LnArry[Line].Touched = FALSE;
  450.     WinStat->LnArry[Line].StartCol = WinPtr->_maxx;
  451.     WinStat->LnArry[Line].EndCol = 0;
  452.   }
  453.   WinPtr->_curx = 0;
  454.   WinPtr->_cury = 0;
  455.   WinPtr->_cls = TRUE;
  456.   return OK;
  457. }
  458.  
  459. werase(WinPtr)
  460.      WINDOW *WinPtr;
  461. {
  462.   int Line, Col;
  463.   struct WindowState *WinStat;
  464.   
  465.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  466.     return ERR;
  467.   
  468.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  469.     return ERR;
  470.   
  471.   /* Blank screen image */
  472.   for(Line=0; Line<WinStat->NLines; Line++) {
  473.     memset(WinStat->LnArry[Line].Line, ' ', WinPtr->_maxx + 1);
  474.     for(Col = 0; Col <= WinPtr->_maxx; Col++)
  475.       WinStat->LnArry[Line].ATTRS[Col] = WinPtr->_attrs;
  476.     WinStat->LnArry[Line].Touched = TRUE;
  477.     WinStat->LnArry[Line].StartCol = 0;
  478.     WinStat->LnArry[Line].EndCol = WinPtr->_maxx;
  479.   }
  480.   WinPtr->_curx = 0;
  481.   WinPtr->_cury = 0;
  482.   return OK;
  483. }
  484.  
  485. clearok(WinPtr, flag)
  486.      WINDOW *WinPtr;
  487.      int flag;
  488. {
  489.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  490.     return ERR;
  491.   
  492.   WinPtr->_clear = (flag) ? TRUE : FALSE;
  493.   
  494.   return OK;
  495. }
  496.  
  497. wclrtoeol(WinPtr)
  498.      WINDOW *WinPtr;
  499. {
  500.   short x, y;
  501.   int len;
  502.   char Buffer[100];
  503.   
  504.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  505.     return ERR;
  506.   x = WinPtr->_curx;
  507.   y = WinPtr->_cury;
  508.   
  509.   len = WinPtr->_maxx - WinPtr->_curx + 1;
  510.   memset(Buffer, ' ', len);
  511.   Buffer[len] = '\0';
  512.   
  513.   waddstr(WinPtr, Buffer);
  514.   wmove(WinPtr, y, x);
  515.   
  516.   return OK;
  517. }
  518.  
  519. wclrtobot(WinPtr)
  520.      WINDOW *WinPtr;
  521. {
  522.   short x, y;
  523.   int i;
  524.   
  525.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  526.     return ERR;
  527.   x = WinPtr->_curx;
  528.   y = WinPtr->_cury;
  529.   
  530.   wclrtoeol(WinPtr);
  531.   for(i = WinPtr->_cury + 1; i <= WinPtr->_maxy; i++) {
  532.     wmove(WinPtr, i, 0);
  533.     wclrtoeol(WinPtr);
  534.   }
  535.   wmove(WinPtr, y, x);
  536.   
  537.   return OK;
  538. }
  539.  
  540. static int GetNextChar(WinPtr)
  541.      WINDOW *WinPtr;
  542. {
  543.   static unsigned char buffer[RAWBUFSIZ], BufPos = 0, NumChars = 0;
  544.   int Class, i;
  545.   struct IntuiMessage *Message;
  546.   static struct InputEvent ievent = { NULL, IECLASS_RAWKEY, 0, 0, 0 };
  547.   
  548.   if(BufPos < NumChars)  /* If we still hav some chars then return next */
  549.     return (int)buffer[BufPos++];
  550.   
  551.   while (BufPos == NumChars) {
  552.     /* Get message if there is one allready queued */
  553.     Message = (struct IntuiMessage *)GetMsg(CursesWindow->UserPort);
  554.     if(!Message) {
  555.       /* Nuffin yet */
  556.       if(WinPtr->_nodelay)  /* If non-blocking return ERR */
  557.     return ERR;
  558.       else {    /* Wait for character */
  559.     Wait(1<<CursesWindow->UserPort->mp_SigBit);
  560.     Message = (struct IntuiMessage *)GetMsg(CursesWindow->UserPort);
  561.       }
  562.     }
  563.     if(!Message)  /* Try again */
  564.       continue;
  565.     
  566.     Class = Message->Class;
  567.     switch(Class) {
  568.     case RAWKEY:
  569.       BufPos = 0;
  570.       ievent.ie_Code = Message->Code;
  571.       ievent.ie_Qualifier = Message->Qualifier;
  572.       ievent.ie_position.ie_addr = *((APTR*)Message->IAddress);
  573.       NumChars = RawKeyConvert(&ievent, buffer, RAWBUFSIZ, 0L);
  574.       ReplyMsg((struct Message *)Message);
  575.       if(!NumChars)  /* If no characters then try again */
  576.     break;
  577.       if(CursesFlags & CFLAG_ECHO)
  578.     for(i=0; i<NumChars; i++)
  579.       DoEcho(WinPtr, buffer[i]);
  580.       /* Translate id keypad set to TRUE */
  581.       if(WinPtr->_use_keypad) {
  582.     switch(NumChars) {
  583.     case 1:
  584.       NumChars = 0;  /* Translation will use up all chars */
  585.       return (int)buffer[0];
  586.     case 2:    /* ARROW KEY */
  587.       NumChars = 0;  /* Translation will use up all chars */
  588.       if(buffer[0] != 155)
  589.         return -1;
  590.       switch(buffer[1]) {
  591.       case 65: return KEY_UP;
  592.       case 66: return KEY_DOWN;
  593.       case 67: return KEY_RIGHT;
  594.       case 68: return KEY_LEFT;
  595.       default: return -1;
  596.       }
  597.     case 3:    /* FUNCTION KEY */
  598.       NumChars = 0;  /* Translation will use up all chars */
  599.       if(buffer[0] != 155)
  600.         return -1;
  601.       if(buffer[2] != 126)
  602.         return -1;
  603.       if(buffer[1] == 63)
  604.         return KEY_HELP;
  605.       return KEY_F0 + (buffer[1] - 48);  /* KEY_F0 = F1 */
  606.     default:
  607.       NumChars = 0;  /* Translation will use up all chars */
  608.       return -1;
  609.     }
  610.       }
  611.       break;
  612.     default:
  613.       ReplyMsg((struct Message *)Message);
  614.       break;
  615.     }
  616.   }
  617.   return (int)buffer[BufPos++];
  618. }
  619.  
  620. flushinp()
  621. {
  622.   GetchRPos = 0;
  623.   GetchWPos = 0;
  624.   return OK;
  625. }
  626.  
  627. wgetch(WinPtr)
  628.      WINDOW *WinPtr;
  629. {
  630.   static int buffer[256];  /* Cyclic buffer */
  631.   static unsigned char forward = FALSE;
  632.   int Ret;
  633.   
  634.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  635.     return ERR;
  636.   
  637.   while(GetchRPos == GetchWPos || (!(CursesFlags & CFLAG_CBREAK) && !forward)) {
  638.     if(WinPtr->_nodelay)
  639.       return GetNextChar(WinPtr);
  640.     if((Ret = GetNextChar(WinPtr)) >= 0)
  641.       buffer[GetchWPos++] = Ret;
  642.     if(Ret == (int)'\r')
  643.       forward = TRUE;
  644.   }
  645.   if(buffer[GetchRPos] == '\r') {
  646.     buffer[GetchRPos] = '\n';
  647.     forward = FALSE;
  648.   }
  649.   return((int)buffer[GetchRPos++]);
  650. }
  651.  
  652. wgetstr(WinPtr, ptr)
  653.      WINDOW *WinPtr;
  654.      char *ptr;
  655. {
  656.   char done = FALSE, *BuffStart;
  657.   unsigned char TempFlag;  /* Used to restore flags after */
  658.   
  659.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  660.     return ERR;
  661.   
  662.   BuffStart = ptr;
  663.   
  664.   /* Will need to be in CBREAK mode for this */
  665.   TempFlag = CursesFlags;
  666.   CursesFlags |= CFLAG_CBREAK;
  667.   while(!done) {
  668.     switch(*ptr = wgetch(WinPtr)) {
  669.     case -1:  /* wgetch() returned ERROR */
  670.       *ptr = '\0';
  671.       CursesFlags = TempFlag;
  672.       return -1;
  673.     case '\n':
  674.     case '\r':
  675.       *ptr = '\0';
  676.       done = TRUE;
  677.       break;
  678.     case '\b':
  679.       if(--ptr < BuffStart)  /* Don't move before start */
  680.     ptr = BuffStart;
  681.       else if(CursesFlags & CFLAG_ECHO) {
  682.     /* Do BS SP BS processing */
  683.     mvcur(CursorLine, CursorCol, CursorLine, CursorCol - 1);  /* BS */
  684.     DoEcho(WinPtr, ' ');          /* SP */
  685.     mvcur(CursorLine, CursorCol, CursorLine, CursorCol - 1);  /* BS */
  686.       }
  687.       break;
  688.     default:
  689.       ptr++;
  690.       break;
  691.     }
  692.   }
  693.   CursesFlags = TempFlag;
  694.   return 0;
  695. }
  696.  
  697. winch(WinPtr)
  698.      WINDOW *WinPtr;
  699. {
  700.   struct WindowState *WinStat;
  701.   
  702.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  703.     return ERR;
  704.   
  705.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  706.     return ERR;
  707.   
  708.   return (int)WinStat->LnArry[WinPtr->_cury].Line[WinPtr->_curx];
  709. }
  710.  
  711. static void DoEcho(WinPtr, c)
  712.      WINDOW *WinPtr;
  713.      char c;
  714. {
  715.   short x, y;
  716.   struct WindowState *WinStat;
  717.   
  718.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  719.     return;
  720.   
  721.   if(c == BS || c == CR)        /* Don't echo Backspace or Return */
  722.     return;
  723.   
  724.   x = CursorCol * 8;
  725.   y = 6 + CursorLine * 8;
  726.   ZapCursor();
  727.   SetDrMd(RPort, JAM2);
  728.   SetAPen(RPort, WinPtr->_attrs & 0x0f);
  729.   Move(RPort, x, y);
  730.   Text(RPort, &c, 1);
  731.   DrawCursor();
  732.   /* Update curscr */
  733.   if(WinPtr != curscr) {
  734.     wmove(curscr, CursorLine, CursorCol);
  735.     waddch(curscr, c);
  736.   }
  737.   /* Update Line structure */
  738.   WinStat->LnArry[CursorLine-WinPtr->_begy].Line[CursorCol-WinPtr->_begx] = c;
  739.   WinStat->LnArry[CursorLine-WinPtr->_begy].LRLine[CursorCol-WinPtr->_begx] = c;
  740.   WinStat->LnArry[CursorLine-WinPtr->_begy].ATTRS[CursorCol-WinPtr->_begx] = WinPtr->_attrs;
  741.   WinStat->LnArry[CursorLine-WinPtr->_begy].LRATTRS[CursorCol-WinPtr->_begx] = WinPtr->_attrs;
  742.   /* Move current position one to the right */
  743.   if(++WinPtr->_curx > WinPtr->_maxx)
  744.     WinPtr->_curx = WinPtr->_maxx;
  745.   mvcur(CursorLine, CursorCol, CursorLine, CursorCol + 1);
  746. }
  747.  
  748. wmove(WinPtr, Line, Col)
  749.      WINDOW *WinPtr;
  750.      short Line, Col;
  751. {
  752.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  753.     return ERR;
  754.   
  755.   if(Line<0 || Line>WinPtr->_maxy)
  756.     return ERR;
  757.   if(Col<0 || Col>WinPtr->_maxx)
  758.     return ERR;
  759.   WinPtr -> _cury = Line;
  760.   WinPtr -> _curx = Col;
  761.   WinPtr -> _flags |= CWF_MOVED;
  762.   return OK;
  763. }
  764.  
  765. mvcur(CurLine, CurCol, NewLine, NewCol)
  766.      int CurLine, CurCol, NewLine, NewCol;
  767. {
  768.   /* Could check CurLine and CurCol but this would make it fail too often */
  769.   ZapCursor();
  770.   CursorLine = NewLine;
  771.   CursorCol = NewCol;
  772.   DrawCursor();
  773.   return OK;
  774. }
  775.  
  776. printw(fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
  777.      char *fmt;
  778.      double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
  779. {
  780.   int Ret;
  781.   char buffer[BUFSIZ];
  782.   
  783.   Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
  784.   waddstr(stdscr, buffer);
  785.   return Ret;
  786. }
  787.  
  788. wprintw(WinPtr, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
  789.      WINDOW *WinPtr;
  790.      char *fmt;
  791.      double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
  792. {
  793.   int Ret;
  794.   char buffer[BUFSIZ];
  795.   
  796.   Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
  797.   waddstr(WinPtr, buffer);
  798.   return Ret;
  799. }
  800.  
  801. mvprintw(Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
  802.      short Line, Col;
  803.      char *fmt;
  804.      double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
  805. {
  806.   int Ret;
  807.   char buffer[BUFSIZ];
  808.   
  809.   Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
  810.   wmove(stdscr, Line, Col);
  811.   waddstr(stdscr, buffer);
  812.   return Ret;
  813. }
  814.  
  815. mvwprintw(WinPtr, Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
  816.      WINDOW *WinPtr;
  817.      short Line, Col;
  818.      char *fmt;
  819.      double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
  820. {
  821.   int Ret;
  822.   char buffer[BUFSIZ];
  823.   
  824.   Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
  825.   wmove(WinPtr, Line, Col);
  826.   waddstr(WinPtr, buffer);
  827.   return Ret;
  828. }
  829.  
  830. wrefresh(WinPtr)
  831.      WINDOW *WinPtr;
  832. {
  833.   int i, j;
  834.   unsigned long style;
  835.   short Line;
  836.   struct WindowState *WinStat;
  837.   char Buffer[BUFSIZ];
  838.   void Optimise();
  839.   
  840.   if(WinPtr == curscr)
  841.     touchwin(WinPtr);
  842.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  843.     return ERR;
  844.   ZapCursor();
  845.   /*
  846.    *  It is possible for no printing since last refresh, but for
  847.    *  a move to have been done...
  848.    */
  849.   if(WinPtr->_flags & CWF_MOVED) {
  850.     WinPtr->_flags &= ~CWF_MOVED;
  851.     CursorLine = WinPtr->_cury + WinPtr->_begy;
  852.     CursorCol = WinPtr->_curx + WinPtr->_begx;
  853.   }
  854.   /*
  855.    *  If clearok has been called, then clear on every refresh.
  856.    */
  857.   if(WinPtr->_clear || WinPtr->_cls) {
  858.     WinPtr->_cls = FALSE;
  859.     SetAPen(RPort, 0);
  860.     SetDrMd(RPort, JAM2);
  861.     RectFill(RPort, (WinPtr->_begx * 8), (WinPtr->_begy * 8),
  862.          ((WinPtr->_begx + WinPtr->_maxx) * 8) + 7,
  863.          ((WinPtr->_begy + WinPtr->_maxy) * 8 + 7));
  864.   }
  865.   if(CursesFlags & CFLAG_CURSOR) {
  866.     CursorLine = WinPtr->_cury + WinPtr->_begy;
  867.     CursorCol = WinPtr->_curx + WinPtr->_begx;
  868.   }
  869.   for(Line=0; Line<WinStat->NLines; Line++) {
  870.     /* if clearok set then must refresh everything */
  871.     if(WinPtr->_clear) {
  872.       memset(WinStat->LnArry[Line].LRLine, ' ', WinPtr->_maxx+1);
  873.       WinStat->LnArry[Line].Touched = TRUE;
  874.       WinStat->LnArry[Line].StartCol = 0;
  875.       WinStat->LnArry[Line].EndCol = WinPtr->_maxx;
  876.     }
  877.     Optimise(&WinStat->LnArry[Line]);
  878.     if(WinStat->LnArry[Line].Touched) {
  879.       j = WinStat->LnArry[Line].StartCol;
  880.       for(i=WinStat->LnArry[Line].StartCol + 1; i<=WinStat->LnArry[Line].EndCol; i++) {
  881.     if(WinStat->LnArry[Line].ATTRS[i] != WinStat->LnArry[Line].ATTRS[j]) {
  882.       /* Print what we've got */
  883.       SetAPen(RPort, WinStat->LnArry[Line].ATTRS[j] & 017);
  884.       if(WinStat->LnArry[Line].ATTRS[j] & (A_REVERSE | A_STANDOUT))
  885.         SetDrMd(RPort, JAM2|INVERSVID);
  886.       else
  887.         SetDrMd(RPort, JAM2);
  888.       style = FS_NORMAL;
  889.       if(WinStat->LnArry[Line].ATTRS[j] & A_BOLD)
  890.         style |= FSF_BOLD;
  891.       if(WinStat->LnArry[Line].ATTRS[j] & A_UNDERLINE)
  892.         style |= FSF_UNDERLINED;
  893.       SetSoftStyle(RPort, style, ~0L);
  894.       Move(RPort, (j+WinPtr->_begx) * 8, 6 + (Line+WinPtr->_begy) * 8);
  895.       Text(RPort, &WinStat->LnArry[Line].Line[j], i-j);
  896.       /*
  897.        *  Update the record of the current screen state.
  898.        */
  899.       if(WinPtr != curscr) {
  900.         wmove(curscr, Line+WinPtr->_begy, j+WinPtr->_begx);
  901.         memcpy(Buffer, &WinStat->LnArry[Line].Line[j], i-j);
  902.         Buffer[i-j] = '\0';
  903.         waddstr(curscr, Buffer);
  904.       }
  905.       j = i;
  906.     }
  907.       }
  908.       if(j < i) {
  909.     SetAPen(RPort, WinStat->LnArry[Line].ATTRS[j] & 017);
  910.     if(WinStat->LnArry[Line].ATTRS[j] & (A_STANDOUT | A_REVERSE))
  911.       SetDrMd(RPort, JAM2|INVERSVID);
  912.     else
  913.       SetDrMd(RPort, JAM2);
  914.     style = FS_NORMAL;
  915.     if(WinStat->LnArry[Line].ATTRS[j] & A_BOLD)
  916.       style |= FSF_BOLD;
  917.     if(WinStat->LnArry[Line].ATTRS[j] & A_UNDERLINE)
  918.       style |= FSF_UNDERLINED;
  919.     SetSoftStyle(RPort, style, ~0L);
  920.     Move(RPort, (j+WinPtr->_begx) * 8, 6 + (Line+WinPtr->_begy) * 8);
  921.     Text(RPort, &(WinStat->LnArry[Line].Line[j]), i-j);
  922.     /*
  923.      *  Update the record of the current screen state.
  924.      */
  925.     if(WinPtr != curscr) {
  926.       wmove(curscr, Line+WinPtr->_begy, j+WinPtr->_begx);
  927.       memcpy(Buffer, &WinStat->LnArry[Line].Line[j], i-j);
  928.       Buffer[i-j] = '\0';
  929.       waddstr(curscr, Buffer);
  930.     }
  931.       }
  932.       WinStat->LnArry[Line].Touched = FALSE;
  933.       WinStat->LnArry[Line].StartCol = WinPtr->_maxx;
  934.       WinStat->LnArry[Line].EndCol = 0;
  935.     }
  936.     /*
  937.      *  Copy line and attrs to LR for Optimise code
  938.      */
  939.     memcpy(WinStat->LnArry[Line].LRLine, WinStat->LnArry[Line].Line, WinPtr->_maxx+1);
  940.     memcpy(WinStat->LnArry[Line].LRATTRS, WinStat->LnArry[Line].ATTRS, sizeof(short) * (WinPtr->_maxx+1));
  941.   }
  942.   DrawCursor();
  943.   return OK;
  944. }
  945.  
  946. static void ToggleCursor(Line, Col)
  947. {
  948.   SetDrMd(RPort, JAM2 | INVERSVID | COMPLEMENT);
  949.   Move(RPort, Col*8, 6 + Line*8);
  950.   Text(RPort, " ", 1);
  951. }
  952.  
  953. static void
  954.   ZapCursor()
  955. {
  956.   /* If there was a cursor then blank it */
  957.   if(LCursorCol >= 0 && LCursorLine >= 0)
  958.     ToggleCursor(LCursorLine, LCursorCol);
  959.   
  960.   LCursorCol = LCursorLine = -1;
  961. }
  962.  
  963. static void DrawCursor()
  964. {
  965.   /* Draw cursor */
  966.   if(CursesFlags & CFLAG_CURSOR)
  967.     ToggleCursor(CursorLine, CursorCol);
  968.   
  969.   if(CursesFlags & CFLAG_CURSOR) {
  970.     LCursorCol = CursorCol;
  971.     LCursorLine = CursorLine;
  972.   } else {
  973.     LCursorCol = -1;
  974.     LCursorLine = -1;
  975.   }
  976. }
  977.  
  978. scanw(fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
  979.      char *fmt;
  980.      long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
  981. {
  982.   char buffer[BUFSIZ];
  983.   
  984.   wgetstr(stdscr, buffer);
  985.   return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
  986. }
  987.  
  988. wscanw(WinPtr, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
  989.      WINDOW *WinPtr;
  990.      char *fmt;
  991.      long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
  992. {
  993.   char buffer[BUFSIZ];
  994.   
  995.   wgetstr(WinPtr, buffer);
  996.   return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
  997. }
  998.  
  999. mvscanw(Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
  1000.      short Line, Col;
  1001.      char *fmt;
  1002.      long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
  1003. {
  1004.   char buffer[BUFSIZ];
  1005.   
  1006.   wmove(stdscr, Line, Col);
  1007.   wgetstr(stdscr, buffer);
  1008.   return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
  1009. }
  1010.  
  1011. mvwscanw(WinPtr, Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
  1012.      WINDOW *WinPtr;
  1013.      short Line, Col;
  1014.      char *fmt;
  1015.      long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
  1016. {
  1017.   char buffer[BUFSIZ];
  1018.   
  1019.   wmove(WinPtr, Line, Col);
  1020.   wgetstr(WinPtr, buffer);
  1021.   return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
  1022. }
  1023.  
  1024. wstandout(WinPtr)
  1025.      WINDOW *WinPtr;
  1026. {
  1027.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1028.     return ERR;
  1029.   
  1030.   WinPtr->_attrs |= A_STANDOUT;
  1031. }
  1032.  
  1033. wstandend(WinPtr)
  1034.      WINDOW *WinPtr;
  1035. {
  1036.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1037.     return ERR;
  1038.   
  1039.   WinPtr->_attrs &= ~A_STANDOUT;
  1040. }
  1041.  
  1042. wattrset(WinPtr, attr)
  1043.      WINDOW *WinPtr;
  1044.      short attr;
  1045. {
  1046.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1047.     return ERR;
  1048.   
  1049.   /*
  1050.    *  Older code may inadvertently reset the attributes and set the
  1051.    *  forground colour to 0, in this case, set it to white.
  1052.    */
  1053.   if(!(attr & 017))
  1054.     attr |= COLOR_WHITE;
  1055.   
  1056.   WinPtr->_attrs = attr;
  1057.   return OK;
  1058. }
  1059.  
  1060. wattron(WinPtr, attr)
  1061.      WINDOW *WinPtr;
  1062.      short attr;
  1063. {
  1064.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1065.     return ERR;
  1066.   
  1067.   /* If attributes contain a colour change then mask off old colour */
  1068.   if(attr & 017)
  1069.     WinPtr->_attrs &= ~017;
  1070.   
  1071.   WinPtr->_attrs |= attr;
  1072.   return OK;
  1073. }
  1074.  
  1075. wattroff(WinPtr, attr)
  1076.      WINDOW *WinPtr;
  1077.      short attr;
  1078. {
  1079.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1080.     return ERR;
  1081.   
  1082.   WinPtr->_attrs &= ~attr;
  1083.   return OK;
  1084. }
  1085.  
  1086. cbreak()
  1087. {
  1088.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1089.     return ERR;
  1090.   
  1091.   CursesFlags |= CFLAG_CBREAK;
  1092.   return OK;
  1093. }
  1094.  
  1095. nocbreak()
  1096. {
  1097.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1098.     return ERR;
  1099.   
  1100.   CursesFlags &= ~CFLAG_CBREAK;
  1101.   return OK;
  1102. }
  1103.  
  1104. raw()
  1105. {
  1106.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1107.     return ERR;
  1108.   
  1109.   CursesFlags |= CFLAG_CBREAK;
  1110.   return OK;
  1111. }
  1112.  
  1113. noraw()
  1114. {
  1115.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1116.     return ERR;
  1117.   
  1118.   CursesFlags &= ~CFLAG_CBREAK;
  1119.   return OK;
  1120. }
  1121.  
  1122. idlok(WinPtr, flag)
  1123.      WINDOW *WinPtr;
  1124.      int flag;
  1125. {
  1126.   /* This function is to enable hardware insert/delete line */
  1127.   return OK;
  1128. }
  1129.  
  1130. winsertln(WinPtr)
  1131.      WINDOW *WinPtr;
  1132. {
  1133.   Scroll(WinPtr, WinPtr->_cury, WinPtr->_maxy, SCROLL_DOWN);
  1134.   return OK;
  1135. }
  1136.  
  1137. wdeleteln(WinPtr)
  1138.      WINDOW *WinPtr;
  1139. {
  1140.   Scroll(WinPtr, WinPtr->_cury, WinPtr->_maxy, SCROLL_UP);
  1141.   return OK;
  1142. }
  1143.  
  1144. nodelay(WinPtr, flag)
  1145.      WINDOW *WinPtr;
  1146.      int flag;
  1147. {
  1148.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1149.     return ERR;
  1150.   
  1151.   WinPtr->_nodelay = flag;
  1152.   return OK;
  1153. }
  1154.  
  1155. echo()
  1156. {
  1157.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1158.     return ERR;
  1159.   
  1160.   CursesFlags |= CFLAG_ECHO;
  1161.   return OK;
  1162. }
  1163.  
  1164. noecho()
  1165. {
  1166.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1167.     return ERR;
  1168.   
  1169.   CursesFlags &= ~CFLAG_ECHO;
  1170.   return OK;
  1171. }
  1172.  
  1173. keypad(WinPtr, flag)
  1174.      WINDOW *WinPtr;
  1175.      char flag;
  1176. {
  1177.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1178.     return ERR;
  1179.   
  1180.   WinPtr->_use_keypad = flag?TRUE:FALSE;
  1181.   
  1182.   return OK;
  1183. }
  1184.  
  1185. beep()
  1186. {
  1187.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1188.     return ERR;
  1189.   
  1190.   AIOptr = (struct IOAudio *) AllocMem(sizeof(struct IOAudio), MEMF_CHIP|MEMF_PUBLIC);
  1191.   if(!AIOptr)
  1192.     exit(1);
  1193.   
  1194.   port = (struct MsgPort *)CreatePort(0, 0);
  1195.   if(!port) {
  1196.     FreeMem(AIOptr, sizeof(struct IOAudio));
  1197.     return ERR;
  1198.   }
  1199.   
  1200.   AIOptr->ioa_Request.io_Message.mn_ReplyPort = port;
  1201.   AIOptr->ioa_Request.io_Message.mn_Node.ln_Pri = 0;
  1202.   AIOptr->ioa_Request.io_Command = ADCMD_ALLOCATE;
  1203.   AIOptr->ioa_Request.io_Flags = ADIOF_NOWAIT;
  1204.   AIOptr->ioa_AllocKey = 0;
  1205.   AIOptr->ioa_Data = whichannel;
  1206.   AIOptr->ioa_Length = sizeof(whichannel);
  1207.   
  1208.   device = OpenDevice("audio.device", 0L, (struct IORequest *)AIOptr, 0L);
  1209.   if(device) {
  1210.     printf("Curses beep() - Can't open Audio Device\n");
  1211.     FreeMem(AIOptr, sizeof(struct IOAudio));
  1212.     return ERR;
  1213.   }
  1214.   
  1215.   sound_data = (UBYTE *) AllocMem(SOUNDLENGTH, MEMF_CHIP|MEMF_PUBLIC);
  1216.   if(!sound_data) {
  1217.     FreeMem(AIOptr, sizeof(struct IOAudio));
  1218.     return ERR;
  1219.   }
  1220.   
  1221.   sound_data[0]=127;
  1222.   sound_data[1]=-127;
  1223.   
  1224.   AIOptr->ioa_Request.io_Message.mn_ReplyPort = port;
  1225.   AIOptr->ioa_Request.io_Command = CMD_WRITE;
  1226.   AIOptr->ioa_Request.io_Flags = ADIOF_PERVOL;
  1227.   AIOptr->ioa_Data = sound_data;
  1228.   AIOptr->ioa_Cycles = 200;
  1229.   AIOptr->ioa_Length = SOUNDLENGTH;
  1230.   AIOptr->ioa_Period = 2000;
  1231.   AIOptr->ioa_Volume = 64;
  1232.   
  1233.   BeginIO((struct IORequest *)AIOptr);
  1234.   WaitIO((struct IORequest *)AIOptr);
  1235.   
  1236.   FreeMem(sound_data, SOUNDLENGTH);
  1237.   DeletePort(port);
  1238.   CloseDevice((struct IORequest *)AIOptr);
  1239.   FreeMem(AIOptr, sizeof(struct IOAudio));
  1240. }
  1241.  
  1242. flash()
  1243. {
  1244.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1245.     return ERR;
  1246.   
  1247.   DisplayBeep(CursesScreen);
  1248. }
  1249.  
  1250. leaveok(WinPtr, flag)
  1251.      WINDOW *WinPtr;
  1252.      int flag;
  1253. {
  1254.   if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
  1255.     return ERR;
  1256.   
  1257.   if(flag) {
  1258.     CursorCol = CursorLine = -1;
  1259.     CursesFlags &= ~CFLAG_CURSOR;
  1260.   } else {
  1261.     CursesFlags |= CFLAG_CURSOR;
  1262.   }
  1263.   return OK;
  1264. }
  1265.  
  1266. resetty()
  1267. {
  1268.   return OK;
  1269. }
  1270.  
  1271. savetty()
  1272. {
  1273.   return OK;
  1274. }
  1275.  
  1276. resetterm()
  1277. {
  1278.   return OK;
  1279. }
  1280.  
  1281. fixterm()
  1282. {
  1283.   return OK;
  1284. }
  1285.  
  1286. saveterm()
  1287. {
  1288.   return OK;
  1289. }
  1290.  
  1291. baudrate()
  1292. {
  1293.   return 9600;
  1294. }
  1295.  
  1296. nl()
  1297. {
  1298.   CursesFlags |= CFLAG_NLCR;
  1299.   return OK;
  1300. }
  1301.  
  1302. nonl()
  1303. {
  1304.   CursesFlags &= ~CFLAG_NLCR;
  1305.   return OK;
  1306. }
  1307.  
  1308. crmode()
  1309. {
  1310.   return (cbreak());
  1311. }
  1312.  
  1313. nocrmode()
  1314. {
  1315.   return (nocbreak());
  1316. }
  1317.  
  1318. box(WinPtr, vert, hor)
  1319.      WINDOW *WinPtr;
  1320.      char vert, hor;
  1321. {
  1322.   int i;
  1323.   short CurY, CurX;
  1324.   
  1325.   CurY = WinPtr->_cury;
  1326.   CurX = WinPtr->_curx;
  1327.   
  1328.   if(vert < 32 || vert > 126)
  1329.     vert = '|';
  1330.   if(hor < 32 || hor > 126)
  1331.     hor = '-';
  1332.   
  1333.   for(i=0; i<=WinPtr->_maxx; i++) {
  1334.     mvwaddch(WinPtr, 0, i, hor);  /* Top horizontal */
  1335.     mvwaddch(WinPtr, WinPtr->_maxy, i, hor);  /* Bottom horizontal */
  1336.   }
  1337.   for(i=1; i<WinPtr->_maxy; i++) {
  1338.     mvwaddch(WinPtr, i, 0, vert);  /* Left vertical */
  1339.     mvwaddch(WinPtr, i, WinPtr->_maxx, vert);  /* Right vertical */
  1340.   }
  1341.   WinPtr -> _cury = CurY;
  1342.   WinPtr -> _curx = CurX;
  1343.   return OK;
  1344. }
  1345.  
  1346. WINDOW *subwin(Orig, NLines, NCols, StartLine, StartCol)
  1347.      WINDOW *Orig;
  1348.      unsigned int NLines, NCols, StartLine, StartCol;
  1349. {
  1350.   WINDOW *WinPtr, *CreatWindow();
  1351.   
  1352.   if(!(WinPtr = CreatWindow(NLines, NCols, StartLine, StartCol, Orig))) {
  1353.     printf("WARNING - subwin() failed, returning stdscr !!\n");
  1354.     return stdscr;  /* Failed */
  1355.   }
  1356.   return WinPtr;
  1357. }
  1358.  
  1359. WINDOW *newwin(NLines, NCols, StartLine, StartCol)
  1360.      unsigned int NLines, NCols, StartLine, StartCol;
  1361. {
  1362.   WINDOW *WinPtr, *CreatWindow();
  1363.   
  1364.   if(!(WinPtr = CreatWindow(NLines, NCols, StartLine, StartCol, NULL))) {
  1365.     printf("WARNING - newwin() failed, returning stdscr !!\n");
  1366.     return stdscr;  /* Failed */
  1367.   }
  1368.   wclear(WinPtr);
  1369.   return WinPtr;
  1370. }
  1371.  
  1372. /* Orig is NULL and StartCol/Line are not used for newwin() calls */
  1373. static WINDOW *CreatWindow(NLines, NCols, StartLine, StartCol, Orig)
  1374.      int NLines, NCols, StartLine, StartCol;
  1375.      WINDOW *Orig;
  1376. {
  1377.   int Line, j;
  1378.   struct WindowState *NewWinStat, *TmpWinPtr, *OrgWinStat = NULL;
  1379.   char *malloc();
  1380.   
  1381.   /* If either are zero then make them max */
  1382.   if(!NLines)
  1383.     NLines = LINES - StartLine;
  1384.   if(!NCols)
  1385.     NCols = COLS - StartCol;
  1386.   
  1387.   if(NLines>LINES || NCols>COLS || StartLine>LINES || StartCol>COLS)
  1388.     return (struct WINDOW *)NULL;
  1389.   
  1390.   if(StartLine < 0)
  1391.     StartLine = 0;
  1392.   if(StartCol < 0)
  1393.     StartCol = 0;
  1394.   if(Orig)
  1395.     OrgWinStat = (struct WindowState *)Orig->_WinStat;
  1396.   
  1397.   /* Create a new WinStat structure */
  1398.   if((NewWinStat=(struct WindowState *)malloc(sizeof(struct WindowState)))
  1399.      == (struct WindowState *)NULL) {
  1400.     fprintf(stderr, "CreatWindow() - Not enough memory\n");
  1401.     return (struct WINDOW *)NULL;
  1402.   }
  1403.   NewWinStat->ParentWin = Orig;
  1404.   NewWinStat->Next = (struct WindowState *)NULL;
  1405.   NewWinStat->Prev = (struct WindowState *)NULL;
  1406.   NewWinStat->ScrollTop = 0;
  1407.   NewWinStat->ScrollBot = NLines - 1;
  1408.   NewWinStat->NLines = NLines;
  1409.   /* Allocate space for LnArry[] */
  1410.   if(!(NewWinStat->LnArry = (struct LineElement *)malloc(sizeof(struct LineElement)*LINES))) {
  1411.     fprintf(stderr, "CreatWindow() - Not enough memory\n");
  1412.     return (struct WINDOW *)NULL;
  1413.   }
  1414.   /* Allocate space for Line, LRLine e.t.c */
  1415.   for(Line = 0; Line < NLines; Line++) {
  1416.     if(OrgWinStat) {  /* If this is a subwindow */
  1417.       /* Set up pointers into parent window */
  1418.       NewWinStat->LnArry[Line].Line =
  1419.     &OrgWinStat->LnArry[Line+StartLine].Line[StartCol];
  1420.       NewWinStat->LnArry[Line].LRLine =
  1421.     &OrgWinStat->LnArry[Line+StartLine].LRLine[StartCol];
  1422.       NewWinStat->LnArry[Line].ATTRS =
  1423.     &OrgWinStat->LnArry[Line+StartLine].ATTRS[StartCol];
  1424.       NewWinStat->LnArry[Line].LRATTRS =
  1425.     &OrgWinStat->LnArry[Line+StartLine].LRATTRS[StartCol];
  1426.     } else {  /* New window, allocate space for lines */
  1427.       /* malloc lines and ATTRS */
  1428.       if((NewWinStat->LnArry[Line].Line = malloc(NCols)) == NULL) {
  1429.     fprintf(stderr, "CreatWindow() - Not enough memory\n");
  1430.     return (struct WINDOW *)NULL;
  1431.       }
  1432.       if((NewWinStat->LnArry[Line].LRLine = malloc(NCols)) == NULL) {
  1433.     fprintf(stderr, "CreatWindow() - Not enough memory\n");
  1434.     return (struct WINDOW *)NULL;
  1435.       }
  1436.       if((NewWinStat->LnArry[Line].ATTRS =
  1437.       (short *)malloc(NCols*sizeof(short))) == NULL) {
  1438.     fprintf(stderr, "CreatWindow() - Not enough memory\n");
  1439.     return (struct WINDOW *)NULL;
  1440.       }
  1441.       if((NewWinStat->LnArry[Line].LRATTRS =
  1442.       (short *)malloc(NCols*sizeof(short))) == NULL) {
  1443.     fprintf(stderr, "CreatWindow() - Not enough memory\n");
  1444.     return (struct WINDOW *)NULL;
  1445.       }
  1446.       /* The optimiser will untouch any lines not used */
  1447.       memset(NewWinStat->LnArry[Line].LRLine, ' ', NCols);
  1448.       for(j=0; j<NCols; j++)
  1449.     NewWinStat->LnArry[Line].LRATTRS[j] = A_NORMAL | COLOR_WHITE;
  1450.     }
  1451.     NewWinStat->LnArry[Line].Touched = FALSE;
  1452.     NewWinStat->LnArry[Line].StartCol = NCols;
  1453.     NewWinStat->LnArry[Line].EndCol = 0;
  1454.   }
  1455.   /* Add to Window Stat list */
  1456.   if(HeadWindowList) {
  1457.     TmpWinPtr = HeadWindowList;
  1458.     while(TmpWinPtr->Next)
  1459.       TmpWinPtr = TmpWinPtr->Next;
  1460.     TmpWinPtr->Next = NewWinStat;
  1461.     NewWinStat->Prev = TmpWinPtr;
  1462.   } else {
  1463.     /* This is the first window i.e. stdscr */
  1464.     HeadWindowList = NewWinStat;
  1465.   }
  1466.   /* Initialise state of the window structure */
  1467.   NewWinStat->Window._cury = 0;
  1468.   NewWinStat->Window._curx = 0;
  1469.   NewWinStat->Window._maxy = NLines - 1;
  1470.   NewWinStat->Window._maxx = NCols - 1;
  1471.   NewWinStat->Window._begy = StartLine;
  1472.   NewWinStat->Window._begx = StartCol;
  1473.   NewWinStat->Window._flags = 0;
  1474.   NewWinStat->Window._attrs = A_NORMAL | COLOR_WHITE;
  1475.   NewWinStat->Window._clear = FALSE;
  1476.   NewWinStat->Window._cls = TRUE;
  1477.   NewWinStat->Window._scroll = FALSE;
  1478.   NewWinStat->Window._use_keypad = 0;
  1479.   NewWinStat->Window._use_meta = 0;
  1480.   NewWinStat->Window._nodelay = 0;
  1481.   NewWinStat->Window._WinStat = (char *)NewWinStat;
  1482.   
  1483.   return &NewWinStat->Window;
  1484. }
  1485.  
  1486. touchwin(WinPtr)
  1487.      WINDOW *WinPtr;
  1488. {
  1489.   struct WindowState *WinStat;
  1490.   int Line;
  1491.   
  1492.   if(!(CursesFlags & CFLAG_INITSCR))
  1493.     return ERR;
  1494.   
  1495.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  1496.     return ERR;
  1497.   
  1498.   for(Line=0; Line<WinStat->NLines; Line++) {
  1499.     WinStat->LnArry[Line].Touched = TRUE;
  1500.     /* Mark whole line as refreshable */
  1501.     WinStat->LnArry[Line].StartCol = 0;
  1502.     WinStat->LnArry[Line].EndCol = WinPtr->_maxx;
  1503.     /* Dump optimisation */
  1504.     memset(WinStat->LnArry[Line].LRLine, 0, WinPtr->_maxx+1);
  1505.   }
  1506.   return OK;
  1507. }
  1508.  
  1509. delwin(WinPtr)
  1510.      WINDOW *WinPtr;
  1511. {
  1512.   struct WindowState *WinStat;
  1513.   int LineNo;
  1514.   
  1515.   if(!(CursesFlags & CFLAG_INITSCR))
  1516.     return ERR;
  1517.   
  1518.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  1519.     return ERR;
  1520.   
  1521.   if(!WinStat->ParentWin) {
  1522.     /* If it's a real window, free up Line, LRLine, ATTRS, LRATTRS */
  1523.     for(LineNo=0; LineNo<WinStat->NLines; LineNo++) {
  1524.       free(WinStat->LnArry[LineNo].Line);
  1525.       free(WinStat->LnArry[LineNo].LRLine);
  1526.       free(WinStat->LnArry[LineNo].ATTRS);
  1527.       free(WinStat->LnArry[LineNo].LRATTRS);
  1528.     }
  1529.   }
  1530.   /* Free up LnArry[] */
  1531.   free(WinStat->LnArry);
  1532.   /* Remove the winstat from the list */
  1533.   if(WinStat == HeadWindowList) { /* if this is first window (stdscr) */
  1534.     HeadWindowList = WinStat->Next;
  1535.     if(HeadWindowList)
  1536.       HeadWindowList->Prev = (struct WindowState *)NULL;
  1537.   } else {
  1538.     if(WinStat->Next)
  1539.       WinStat->Next->Prev = WinStat->Prev;
  1540.     if(WinStat->Prev)
  1541.       WinStat->Prev->Next = WinStat->Next;
  1542.   }
  1543.   /* Free the winstat */
  1544.   free(WinStat);
  1545.   return OK;
  1546. }
  1547.  
  1548.  
  1549. mvwin(WinPtr, NewLine, NewCol)
  1550.      WINDOW *WinPtr;
  1551.      short NewLine, NewCol;
  1552. {
  1553.   if(!(CursesFlags & CFLAG_INITSCR))
  1554.     return ERR;
  1555.   
  1556.   WinPtr->_begx = NewCol;
  1557.   WinPtr->_begy = NewLine;
  1558.   if(touchwin(WinPtr) == ERR)
  1559.     return ERR;
  1560.   return OK;
  1561. }
  1562.  
  1563. scroll(WinPtr)
  1564.      WINDOW *WinPtr;
  1565. {
  1566.   struct WindowState *WinStat;
  1567.   
  1568.   if(!(CursesFlags & CFLAG_INITSCR))
  1569.     return ERR;
  1570.   
  1571.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  1572.     return ERR;
  1573.   
  1574.   Scroll(WinPtr, WinStat->ScrollTop, WinStat->ScrollBot, SCROLL_UP);
  1575.   return OK;
  1576. }
  1577.  
  1578. static Scroll(WinPtr, Top, Bottom, Direction)
  1579.      WINDOW *WinPtr;
  1580.      int Top, Bottom, Direction;
  1581. {
  1582.   int Step, SLine, DLine, Col;
  1583.   char *TLine, *TLRLine;
  1584.   short *TATTRS, *TLRATTRS;
  1585.   struct WindowState *WinStat;
  1586.   
  1587.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  1588.     return ERR;
  1589.   
  1590.   /* Store pointers to line that will be lost */
  1591.   if(Direction == SCROLL_UP) {
  1592.     Step = +1;
  1593.     DLine = Top;
  1594.     SLine = Top + Step;
  1595.   } else {
  1596.     Step = -1;
  1597.     DLine = Bottom;
  1598.     SLine = Bottom + Step;
  1599.   }
  1600.   TLine = WinStat->LnArry[DLine].Line;
  1601.   TLRLine = WinStat->LnArry[DLine].LRLine;
  1602.   TATTRS = WinStat->LnArry[DLine].ATTRS;
  1603.   TLRATTRS = WinStat->LnArry[DLine].LRATTRS;
  1604.   /* Move the lines */
  1605.   for(;;) {
  1606.     if((Direction == SCROLL_UP) && (DLine >= Bottom))
  1607.       break;  /* Done */
  1608.     if((Direction == SCROLL_DOWN) && (DLine <= Top))
  1609.       break;  /* Done */
  1610.     WinStat->LnArry[DLine].Line = WinStat->LnArry[SLine].Line;
  1611.     WinStat->LnArry[DLine].LRLine = WinStat->LnArry[SLine].LRLine;
  1612.     WinStat->LnArry[DLine].ATTRS = WinStat->LnArry[SLine].ATTRS;
  1613.     WinStat->LnArry[DLine].LRATTRS = WinStat->LnArry[SLine].LRATTRS;
  1614.     for(Col=0; Col <= WinStat->Window._maxx; Col++) {
  1615.       WinStat->LnArry[DLine].ATTRS[Col] = WinStat->Window._attrs;
  1616.       WinStat->LnArry[DLine].LRATTRS[Col] = 0;
  1617.     }
  1618.     SLine += Step;
  1619.     DLine += Step;
  1620.   }
  1621.   /* Blank the Temp line */
  1622.   memset(TLine, ' ', WinStat->Window._maxx+1);
  1623.   memset(TLRLine, 0, WinStat->Window._maxx+1);
  1624.   for(Col=0; Col <= WinStat->Window._maxx; Col++) {
  1625.     TATTRS[Col] = WinStat->Window._attrs;
  1626.     TLRATTRS[Col] = 0;
  1627.   }
  1628.   /* move in temp line */
  1629.   WinStat->LnArry[DLine].Line = TLine;
  1630.   WinStat->LnArry[DLine].LRLine = TLRLine;
  1631.   WinStat->LnArry[DLine].ATTRS = TATTRS;
  1632.   WinStat->LnArry[DLine].LRATTRS = TLRATTRS;
  1633.   
  1634.   return OK;
  1635. }
  1636.  
  1637. wsetscrreg(WinPtr, top, bottom)
  1638.      WINDOW *WinPtr;
  1639.      short top, bottom;
  1640. {
  1641.   struct WindowState *WinStat;
  1642.   
  1643.   if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
  1644.     return ERR;
  1645.   WinStat->ScrollTop = top;
  1646.   WinStat->ScrollBot = bottom;
  1647.   return OK;
  1648. }
  1649.  
  1650. scrollok(WinPtr, flag)
  1651.      WINDOW *WinPtr;
  1652.      int flag;
  1653. {
  1654.   WinPtr->_scroll = (flag) ? TRUE : FALSE;
  1655.   return OK;
  1656. }
  1657.  
  1658. /*
  1659.  *  Simple implementation of wnoutrefresh() and doupdate()
  1660.  *
  1661.  * Date: 8th Oct 1990
  1662.  *
  1663.  * Author: SJR
  1664.  *
  1665.  */
  1666.  
  1667. wnoutrefresh(WinPtr)
  1668.      WINDOW *WinPtr;
  1669. {
  1670.   struct RefreshElement *NewRefEl;
  1671.   
  1672.   if(!(NewRefEl = (struct RefreshElement *)
  1673.        malloc(sizeof(struct RefreshElement))))
  1674.     return ERR;
  1675.   
  1676.   /* Fill the new element in */
  1677.   NewRefEl->Next = (struct RefreshElement *)NULL;
  1678.   NewRefEl->WinPtr = WinPtr;
  1679.   
  1680.   /* Add to start of refresh list */
  1681.   if(HeadRefreshList)
  1682.     NewRefEl->Next = HeadRefreshList;
  1683.   HeadRefreshList = NewRefEl;
  1684. }
  1685.  
  1686. doupdate()
  1687. {
  1688.   struct RefreshElement *ElPtr;
  1689.   void ZapRElList();
  1690.   
  1691.   ElPtr = HeadRefreshList;
  1692.   while(ElPtr) {
  1693.     if(wrefresh(ElPtr->WinPtr) == ERR)
  1694.       return ERR;
  1695.     ElPtr = ElPtr->Next;
  1696.   }
  1697.   ZapRElList(HeadRefreshList);
  1698.   HeadRefreshList = (struct RefreshElement *)NULL;
  1699.   
  1700.   return OK;
  1701. }
  1702.  
  1703. static void ZapRElList(ElPtr)
  1704.      struct RefreshElement *ElPtr;
  1705. {
  1706.   if(!ElPtr)
  1707.     return;
  1708.   if(ElPtr->Next)
  1709.     ZapRElList(ElPtr->Next);  /* Recurse my boy */
  1710.   free(ElPtr);
  1711. }
  1712.  
  1713. static void Optimise(LinePtr)
  1714.      struct LineElement *LinePtr;
  1715. {
  1716.   int i;
  1717.   
  1718.   if(!LinePtr->Touched)
  1719.     return;
  1720.   for(i=LinePtr->StartCol; i<=LinePtr->EndCol; i++) {
  1721.     if((LinePtr->Line[i] != LinePtr->LRLine[i]) ||
  1722.        (LinePtr->ATTRS[i] != LinePtr->LRATTRS[i]))
  1723.       break;
  1724.     LinePtr->StartCol++;
  1725.   }
  1726.   for(i=LinePtr->EndCol; i>=LinePtr->StartCol; i--) {
  1727.     if((LinePtr->Line[i] != LinePtr->LRLine[i]) ||
  1728.        (LinePtr->ATTRS[i] != LinePtr->LRATTRS[i]))
  1729.       break;
  1730.     LinePtr->EndCol--;
  1731.   }
  1732.   if(LinePtr->StartCol > LinePtr->EndCol)
  1733.     LinePtr->Touched = FALSE;
  1734. }
  1735.